package fatworm.Parser.Parse;
import java_cup.runtime.*;

%%


%unicode
%cup
%line
%column
%type java_cup.runtime.Symbol
%public
%ignorecase

%{
  StringBuffer string = new StringBuffer();
  
  private Symbol symbol(int type) {
    return new Symbol(type, yyline+1, yycolumn+1);
  }

  private Symbol symbol(int type, Object value) {
    return new Symbol(type, yyline+1, yycolumn+1, value);
  }
  /*
  private void newline() {
}


  
private java_cup.runtime.Symbol tok(int kind, Object value) {
    return new java_cup.runtime.Symbol(kind, yychar, yychar+yylength(), value);
}
*/


	
%}


%{
  private int comment_count = 0;
%} 

LineTerminator = \r|\n|\r\n

WhiteSpace = {LineTerminator} | [ \t\f]

COMMENT_TEXT=([^*/]|[^*]"/"[^*]|[^/]"*"[^/]|"*"[^/]|"/"[^*])*

/* identifiers */
Identifier = [a-zA-Z][0-9a-zA-Z_]*

/* integer literals */
DecIntegerLiteral = [0-9]+
FloatLiteral = [0-9]+[.][0-9]+
TimestampLiteral = [\'][0-9][0-9][0-9][0-9][-][0-9][0-9][-][0-9][0-9]{WhiteSpace}[0-9][0-9][:][0-9][0-9][:][0-9][0-9][\']
/* string and character literals */
StringCharacter = [^\n\'\\]

%state STRING
%state COMMENT

%%

<YYINITIAL> {

 
  "select"                        { return symbol(sym.SELECT); }
  "from"                        { return symbol(sym.FROM); }
  "where"                           { return symbol(sym.WHERE); }
  "insert"                          { return symbol(sym.INSERT); }
  "into"                          { return symbol(sym.INTO); }
  "values"                     { return symbol(sym.VALUES); }
  "delete"                           { return symbol(sym.DELETE); }
  "update"                           { return symbol(sym.UPDATE); }
  "set"                          { return symbol(sym.SET); }
  "create"                           { return symbol(sym.CREATE); }
  "table"                         { return symbol(sym.TABLE); }
  "as"                        { return symbol(sym.AS); }
   "index"						{ return symbol(sym.INDEX); }
   "on"							{ return symbol(sym.ON); }		
   "database"					{ return symbol(sym.DATABASE); }
   "drop"						{ return symbol(sym.DROP); }
   "primary"					{ return symbol(sym.PRIMARY); }
   "key"						{ return symbol(sym.KEY); }
   "avg"						{ return symbol(sym.AVG); }
   "count"						{ return symbol(sym.COUNT); }
   "min"						{ return symbol(sym.MIN); }
   "max"						{ return symbol(sym.MAX); }
   "sum"						{ return symbol(sym.SUM); }
   "and"						{ return symbol(sym.AND); }
   "or"							{ return symbol(sym.OR); }
   "exists"						{ return symbol(sym.EXISTS); }
   "any"						{ return symbol(sym.ANY); }
   "in"							{ return symbol(sym.IN); }
   "all"						{ return symbol(sym.ALL); }
   "auto_increment"				{ return symbol(sym.AUTO_INCREMENT); }
   "null"						{ return symbol(sym.NULL); }
   "not"						{ return symbol(sym.NOT); }
   "primary"					{ return symbol(sym.PRIMARY); }
   "key"						{ return symbol(sym.KEY); }
   "use"						{ return symbol(sym.USE); }
   "default"					{ return symbol(sym.DEFAULT); }
   "distinct"					{ return symbol(sym.DISTINCT); }
   "group"						{ return symbol(sym.GROUP); }
   "by"							{ return symbol(sym.BY); }
   "having"						{ return symbol(sym.HAVING); }
   "asc"						{ return symbol(sym.ASC); }
   "desc"						{ return symbol(sym.DESC); }
   "true"						{ return symbol(sym.TRUE); }
   "false"						{ return symbol(sym.FALSE); }
   "unique"						{ return symbol(sym.UNIQUE); }
   "order"						{ return symbol(sym.ORDER); }
  /* separators */
  "("                            { return symbol(sym.LPAREN); }
  ")"                            { return symbol(sym.RPAREN); }
  ","                            { return symbol(sym.COMMA); }
  "."                            { return symbol(sym.DOT); }
  
  /* operators */
  "="                            { return symbol(sym.EQ); }
  ">"                            { return symbol(sym.GT); }
  "<"                            { return symbol(sym.LT); }
  "<="                           { return symbol(sym.LE); }
  ">="                           { return symbol(sym.GE); }
  "<>"                           { return symbol(sym.NEQ); }
  "+"                            { return symbol(sym.PLUS); }
  "-"                            { return symbol(sym.MINUS); }
  "*"                            { return symbol(sym.MULT); }
  "/"                            { return symbol(sym.DIV); }
  "%"                            { return symbol(sym.MOD); }
  
  
  /* string literal */
  \'                             { yybegin(STRING); string.setLength(0); }

  "/*" 							 { yybegin(COMMENT); comment_count++; }

  {DecIntegerLiteral}            { return symbol(sym.INTEGER_LITERAL, new Integer(yytext())); }
  {TimestampLiteral}			 { return symbol(sym.TIMESTAMP_LITERAL, new String(yytext()));}
	{FloatLiteral}				 { return symbol(sym.FLOAT_LITERAL, new String(yytext()));}
  /* whitespace */
  {WhiteSpace}                   { /* ignore */ }

  /* identifiers */ 
  {Identifier}                   { return symbol(sym.IDENTIFIER, yytext()); }  
}


<COMMENT> {
  "/*" { comment_count++; }
  "*/" { if (--comment_count == 0) yybegin(YYINITIAL); }
  {COMMENT_TEXT} { }
}

<STRING> {
  \'                             { yybegin(YYINITIAL); return symbol(sym.STRING_LITERAL, string.toString()); }
  
  {StringCharacter}+             { string.append( yytext() ); }
  
  /* escape sequences */
  "\\t"                          { string.append( '\t' ); }
  "\\n"                          { string.append( '\n' ); }
  "\\\'"                         { string.append( '\'' ); }
  "\\\\"                         { string.append( '\\' ); }
  \\[0-3][0-9][0-9]  			 { char val = (char) Integer.parseInt(yytext().substring(1),8);
                        				   string.append( val ); }
  \\{WhiteSpace}*\\				 { /* ignore */ }
  
  
  
  /* error cases */
  \\.                            { throw new RuntimeException("Illegal escape sequence \""+yytext()+"\""); }
  
}

/* error fallback */
.|\n                             { throw new RuntimeException("Illegal character \""+yytext()+
                                                              "\" at line "+yyline+", column "+yycolumn); }
<<EOF>>                          { return symbol(sym.EOF); }



